package com.atguigu.gmall.list.service.impl;
import com.atguigu.gmall.model.list.SearchAttr;
import com.atguigu.gmall.model.vo.SearchAttrListVo;
import com.atguigu.gmall.model.vo.SearchOrderMapVo;
import com.atguigu.gmall.model.vo.SearchTrademarkVo;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.google.common.collect.Lists;

import com.atguigu.gmall.list.service.GoodsSearchService;
import com.atguigu.gmall.model.list.Goods;
import com.atguigu.gmall.model.list.SearchParam;
import com.atguigu.gmall.model.vo.GoodsSearchResultVo;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.nested.NestedAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.nested.NestedAggregator;
import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.HighlightQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.data.querydsl.QPageRequest;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author A
 * @version 1.0
 * @description: TODO
 * @date 2025/9/7 1:38
 */

@Service
public class GoodsSearchServiceImpl implements GoodsSearchService {
    @Autowired
    ElasticsearchRestTemplate restTemplate;

    @Override
    public GoodsSearchResultVo search(SearchParam searchParam) {
        //构造查询条件
        Query query = buildSearchQuery(searchParam);
        SearchHits<Goods> goodsHits = restTemplate.search(query, Goods.class, IndexCoordinates.of("goods"));
        //包装结果
        GoodsSearchResultVo goodsSearchResultVo=wrapSearchData(goodsHits,searchParam);

        return goodsSearchResultVo;
    }
    //解析结果,将数据封装到GoodsSearchResultVo中
    private GoodsSearchResultVo wrapSearchData(SearchHits<Goods> goodsHits, SearchParam searchParam) {
        GoodsSearchResultVo resultVo = new GoodsSearchResultVo();

        resultVo.setSearchParam(searchParam);
        //品牌面包屑；自己拼成  品牌：VIVO  的效果
        if (StringUtils.isNotBlank(searchParam.getTrademark())){
            String[] split = searchParam.getTrademark().split(":");
            String trademarkName = split[1];
            resultVo.setTrademarkParam("品牌:"+trademarkName);
        }
        //返回给前端已经点击的url
        String url=getClickUrl(searchParam);
        resultVo.setUrlParam(url);
        //平台属性面包屑
        String[] props = searchParam.getProps();
        ArrayList<SearchAttr> searchAttrs = Lists.newArrayList();
        if (props != null) {
            for (String prop : props) {
                String[] split = prop.split(":");
                SearchAttr searchAttr = new SearchAttr();
                searchAttr.setAttrId(Long.parseLong(split[0]));
                searchAttr.setAttrValue(split[1]);   //属性值
                searchAttr.setAttrName(split[2]);   //属性名
                searchAttrs.add(searchAttr);
            }
        }
        resultVo.setPropsParamList(searchAttrs);
        //检索区：品牌列表信息
        List<SearchTrademarkVo> trademarkList=getTrademarkList(goodsHits);
        resultVo.setTrademarkList(trademarkList);

        //检索区：平台属性列表信息
        List<SearchAttrListVo> attrsList=getAttrsList(goodsHits);
        resultVo.setAttrsList(attrsList);
        //排序条件
        SearchOrderMapVo orderMapVo = new SearchOrderMapVo();
        String order = searchParam.getOrder();
        if (order != null){
            String[] split = order.split(":");
            orderMapVo.setType(split[0]);
            orderMapVo.setSort(split[1]);
        }
        resultVo.setOrderMap(orderMapVo);

        //商品列表
        ArrayList<Goods> goodsList = Lists.newArrayList();
        goodsHits.forEach(searchHit -> {
            Goods goods = searchHit.getContent();
            //高亮处理
            if (searchParam.getKeyword()!=null){
                goods.setTitle(searchHit.getHighlightField("title").get(0));
            }
            goodsList.add(goods);
        });
        resultVo.setGoodsList(goodsList);

        //页码
        resultVo.setPageNo(searchParam.getPageNo());
        long totalHits = goodsHits.getTotalHits(); //总记录数
        Integer totalPages = (int) (totalHits % searchParam.getPageSize() ==0? totalHits/searchParam.getPageSize():totalHits/searchParam.getPageSize()+1);
        resultVo.setTotalPages(totalPages);


        return resultVo;
    }
    //检索区：平台属性列表信息
    private List<SearchAttrListVo> getAttrsList(SearchHits<Goods> goodsHits) {
        List<SearchAttrListVo> attrsList=Lists.newArrayList();
        Aggregations aggregations = goodsHits.getAggregations();
        ParsedNested attrsAgg = aggregations.get("attrsAgg");
        ParsedLongTerms attrIdAgg = attrsAgg.getAggregations().get("attrIdAgg");
        for (Terms.Bucket bucket : attrIdAgg.getBuckets()) {
            SearchAttrListVo searchAttrListVo = new SearchAttrListVo();
            searchAttrListVo.setAttrId(bucket.getKeyAsNumber().longValue());
            ParsedStringTerms attrNameAgg = bucket.getAggregations().get("attrNameAgg");
            String keyAsString = attrNameAgg.getBuckets().get(0).getKeyAsString();
            searchAttrListVo.setAttrName(keyAsString);
            List<String> attrValueList = Lists.newArrayList();
            ParsedStringTerms attrValueAgg = bucket.getAggregations().get("attrValueAgg");
            for (Terms.Bucket attrValueAggBucket : attrValueAgg.getBuckets()) {
                attrValueList.add(attrValueAggBucket.getKeyAsString());
            }
            searchAttrListVo.setAttrValueList(attrValueList);
            attrsList.add(searchAttrListVo);
        }
        return attrsList;
    }

    //从goodsHits中获取品牌列表信息
    private List<SearchTrademarkVo> getTrademarkList(SearchHits<Goods> goodsHits) {
        List<SearchTrademarkVo> trademarkList=Lists.newArrayList();
        Aggregations aggregations = goodsHits.getAggregations();
        ParsedLongTerms tmIdAgg = aggregations.get("tmIdAgg");
        for (Terms.Bucket bucket : tmIdAgg.getBuckets()) {
            SearchTrademarkVo trademarkVo = new SearchTrademarkVo();
            trademarkVo.setTmId(bucket.getKeyAsNumber().longValue());
            ParsedStringTerms tmNameAgg = bucket.getAggregations().get("tmNameAgg");
            trademarkVo.setTmName(tmNameAgg.getBuckets().get(0).getKeyAsString());
            ParsedStringTerms tmLogoAgg = bucket.getAggregations().get("tmLogoAgg");
            trademarkVo.setTmLogoUrl(tmLogoAgg.getBuckets().get(0).getKeyAsString());
            trademarkList.add(trademarkVo);
        }
        return trademarkList;
    }

    //拼接点击的url
    private String getClickUrl(SearchParam searchParam) {
        String urlPrefix = "list.html?";
        StringBuilder stringBuilder = new StringBuilder(urlPrefix);
        if (searchParam.getCategory1Id() != null){
            stringBuilder.append("&category1Id=").append(searchParam.getCategory1Id());
        }
        if (searchParam.getCategory2Id() != null){
            stringBuilder.append("&category2Id=").append(searchParam.getCategory2Id());
        }
        if (searchParam.getCategory3Id() != null){
            stringBuilder.append("&category3Id=").append(searchParam.getCategory3Id());
        }
        if (StringUtils.isNotBlank(searchParam.getTrademark())){
            stringBuilder.append("&trademark=").append(searchParam.getTrademark());
        }
        if (StringUtils.isNotBlank(searchParam.getKeyword())){
            stringBuilder.append("&keyword=").append(searchParam.getKeyword());
        }
        if (searchParam.getProps() != null) {
            for (String prop : searchParam.getProps()) {
                stringBuilder.append("&props=").append(prop);
            }
        }

        return stringBuilder.toString();
    }

    //构造查询条件
    private Query buildSearchQuery(SearchParam searchParam) {
        NativeSearchQuery dsl = null;

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        if (searchParam.getCategory1Id() != null) {
            boolQuery.must(QueryBuilders.termQuery("category1Id", searchParam.getCategory1Id()));
        }
        if (searchParam.getCategory2Id() != null) {
            boolQuery.must(QueryBuilders.termQuery("category2Id", searchParam.getCategory2Id()));
        }
        if (searchParam.getCategory3Id() != null) {
            boolQuery.must(QueryBuilders.termQuery("category3Id", searchParam.getCategory3Id()));
        }
        // trademark=2:华为
        if (searchParam.getTrademark() != null) {
            boolQuery.must(QueryBuilders.termQuery("tmId", searchParam.getTrademark().split(":")[0]));
        }
        //检索的关键字
        if (searchParam.getKeyword() != null) {
            boolQuery.must(QueryBuilders.matchQuery("title", searchParam.getKeyword()));
        }
        // props=23:4G:运行内存
        if (searchParam.getProps() != null) {
            for (String prop : searchParam.getProps()) {
                String[] split = prop.split(":");
                BoolQueryBuilder nestedBoolQuery = QueryBuilders.boolQuery();
                nestedBoolQuery.must(QueryBuilders.termQuery("attrs.attrId", split[0]));
                nestedBoolQuery.must(QueryBuilders.termQuery("attrs.attrValue", split[1]));
                boolQuery.must(QueryBuilders.nestedQuery("attrs", nestedBoolQuery, ScoreMode.None));
            }
        }
        dsl = new NativeSearchQuery(boolQuery);
        // 排序规则
        // 1:hotScore 2:price
        //private String order = "1:desc"; // 1：综合排序/热点  2：价格
        if (searchParam.getOrder() != null) {
            String[] split = searchParam.getOrder().split(":");
            String sortField = "";
            switch (split[0]) {
                case "1":
                    sortField = "hotScore";break;
                case "2":
                    sortField ="price";break;
                default:
                    sortField ="hotScore";break;
            }
            dsl.addSort(Sort.by(Sort.Direction.fromString(split[1]), sortField));
        }
        //分页
        PageRequest pageRequest = PageRequest.of(searchParam.getPageNo() - 1, searchParam.getPageSize());
        //构建高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        HighlightQuery highlightQuery = new HighlightQuery(highlightBuilder);
        dsl.setHighlightQuery(highlightQuery);
        //分组聚会
        //1.品牌聚合
        TermsAggregationBuilder brandAgg = AggregationBuilders.terms("tmIdAgg").field("tmId").size(100);
        //1.1品牌名称聚合
        TermsAggregationBuilder brandNameAgg = AggregationBuilders.terms("tmNameAgg").field("tmName").size(100);
        //1.2品牌logo聚合
        TermsAggregationBuilder brandLogoAgg = AggregationBuilders.terms("tmLogoAgg").field("tmLogoUrl").size(100);
        brandAgg.subAggregation(brandNameAgg).subAggregation(brandLogoAgg);
        //2.属性聚合
        NestedAggregationBuilder attrsAgg = AggregationBuilders.nested("attrsAgg", "attrs");
        //2,1.属性id聚合
        TermsAggregationBuilder attrIdAgg = AggregationBuilders.terms("attrIdAgg").field("attrs.attrId").size(100);
        attrsAgg.subAggregation(attrIdAgg);
        //2,2.属性名聚合
        TermsAggregationBuilder attrNameAgg = AggregationBuilders.terms("attrNameAgg").field("attrs.attrName").size(100);
        attrIdAgg.subAggregation(attrNameAgg);
        //2,3.属性值聚合
        TermsAggregationBuilder attrValueAgg = AggregationBuilders.terms("attrValueAgg").field("attrs.attrValue").size(100);


        attrIdAgg.subAggregation(attrValueAgg);
        dsl.addAggregation(brandAgg);
        dsl.addAggregation(attrsAgg);
        dsl.setPageable(pageRequest);
        return dsl;
    }
}
